package zdream.pmfield.test.stage.battle;

import org.junit.Before;
import org.junit.Test;

import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicInteger;

import zdream.pmfield.data.foe.BStat;
import zdream.pmfield.data.foe.Foe;
import zdream.pmfield.data.foe.MoveTemplate;
import zdream.pmfield.stage.Stage;
import zdream.pmfield.stage.StageBuilderForTest;
import zdream.pmfield.stage.director.StageResult;
import zdream.pmfield.stage.message.TurnStartMessage;
import zdream.pmfield.stage.message.StageFinishedMessage;
import zdream.pmfield.storage.FoeTemplateStorage;
import zdream.pmfield.stage.StageWrapper;

import static org.junit.Assert.*;

/**
 * @author Zdream
 * @date 2023-11-15
 * @since 0.0.1
 */
public class Simple1v1BattleCase {
	FoeTemplateStorage storage;
	Foe foe1, foe2;
	MoveTemplate move;

	@Before
	public void before() {
		storage = new FoeTemplateStorage();
		storage.load();
		move = storage.findMoveById(1, 1);

		foe1 = Foe.builder(storage.findFoeById(4))
				.withLevel(20)
				.withMove(move)
				.build();
		foe2 = Foe.builder(storage.findFoeById(1))
				.withLevel(20)
				.withMove(move)
				.build();
	}

	@Test
	public void battle1v1() {
		final Stage stage = Stage.builder()
				.putFoeToOneSide(foe1)
				.putFoeToAnotherSide(foe2)
				.withStorage(storage)
				.build();
		StageWrapper wrapper = StageWrapper.of(stage);
		assertEquals(stage.allFoes.size(), 2);
		AtomicInteger stageFinishedMessageCount = new AtomicInteger(0);

		wrapper.beforeHandleMessage(System.out::println);
		wrapper.onDefaultActionRequest();
		wrapper.onMessage(TurnStartMessage.class, message -> {
			System.out.println();
			System.out.println("----------");
			System.out.println("当前状况如下:");
			System.out.println(stage);
			System.out.println("接下来的顺序:");
			System.out.println(stage.timeline.createExpectOrder());
			System.out.println("----------");
			System.out.println();
		});
		wrapper.onMessage(StageFinishedMessage.class, message1 -> {
			final HashMap<Integer, StageResult.StageResultType> sideResultMap = message1.result.sideResultMap;
			assertTrue(sideResultMap.size() == 2);
			assertNotNull(sideResultMap.get(1));
			assertNotNull(sideResultMap.get(2));

			final HashSet<StageResult.StageResultType> types = new HashSet<>(sideResultMap.values());
			assertTrue(types.contains(StageResult.StageResultType.SUCCESS));
			assertTrue(types.contains(StageResult.StageResultType.FAIL));

			stageFinishedMessageCount.incrementAndGet();
		});

		wrapper.setMaxMessageCount(500);
		wrapper.run();
		assertTrue(stage.isFinished());
		assertEquals(stageFinishedMessageCount.get(), 1);
	}

	@Test
	public void battle1v1WithSameSpeed() {
		Foe foe1 = Foe.builder(storage.findFoeById(28))
				.withLevel(20)
				.withMove(move)
				.skipShuffleVStat()
				.build();
		Foe foe2 = Foe.builder(storage.findFoeById(37))
				.withLevel(20)
				.withMove(move)
				.skipShuffleVStat()
				.build();

		assertEquals(foe1.bStats[BStat.SP.ordinal()], foe2.bStats[BStat.SP.ordinal()]);

		final StageWrapper wrapper = StageBuilderForTest.builder()
				.putFoeToOneSide(foe1)
				.putFoeToAnotherSide(foe2)
				.withStorage(storage)
				.disableDistanceCheck()
				.buildWrapper();
		wrapper.printBeforeHandleMessage();
		wrapper.setMaxMessageCount(500);
		wrapper.onDefaultActionRequest();
		wrapper.run();
	}
}
